package com.xd.study.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.xd.study.R;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by DGF on 2015/5/11.
 * 下拉刷新ListView
 */
public class DownRefreshListView extends ListView implements AbsListView.OnScrollListener {

    /**
     * 刷新数据接口，用于调用Activity中的方法
     * 在Activity中实现该接口
     */
    public interface IRefreshListener{
        void onRefresh();
    }

    /**
     * 刷新数据的监听器
     */
    private IRefreshListener iRefreshListener;

    /**
     * 提供设置接口的方法，以便Activity传入接口
     * @param listener
     */
    public void setRefreshListener(IRefreshListener listener){
        this.iRefreshListener = listener;
    }

    /**
     * 状态
     */
    private final int NONE = 0;
    private final int PULL = 1;//下拉刷新
    private final int RELEASE = 2;//松开刷新
    private final int REFRESHING = 3;//正在刷新

    /**
     * 顶部布局
     */
    private View header;

    /**
     * 布局在父布局中所占的高度
     */
    private int headerHeight;

    /**
     * 图片
     */
    private ImageView imageArrow;
    /**
     * 进度条
     */
    private ProgressBar progressBar;
    /**
     * 刷新文本
     */
    private TextView refreshTxt;
    /**
     * 上次刷新时间
     */
    private TextView timeTxt;

    /**
     * 滚动状态
     */
    private int scrollState = 0;

    /**
     * ListView是否滚动到最顶端
     */
    private boolean bHeader = false;

    /**
     * 鼠标按下的位置
     */
    private float startY;

    /**
     * 移动状态
     */
    private int state = NONE;

    public DownRefreshListView(Context context) {
        super(context);

        init(context);
    }

    public DownRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    public DownRefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context);
    }

    /**
     * 初始化ListView，添加顶部布局文件到ListView中
     */
    private void init(Context context){
        /**
         * 获取顶部布局，添加到ListView中
         */
        LayoutInflater inflater = LayoutInflater.from(context);

        header = inflater.inflate(R.layout.listview_header, null);
        //通知父布局所占的空间
        measureView(header);
        //获取布局所占的高度
        headerHeight = header.getMeasuredHeight();
        Log.i("tag", headerHeight+"");
        //设置布局的上边距为-height，以隐藏布局
        setPadding(-headerHeight);

        this.addHeaderView(header);

        imageArrow = (ImageView)header.findViewById(R.id.header_image);
        refreshTxt = (TextView)header.findViewById(R.id.header_refresh_text);
        timeTxt = (TextView)header.findViewById(R.id.header_time_text);
        progressBar = (ProgressBar)header.findViewById(R.id.header_progressbar);

        this.setOnScrollListener(this);
    }

    /**
     * 通知父布局所占的空间
     * @param view
     */
    private void measureView(View view){
        /**
         * 获取view的布局参数
         */
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params==null){
            params = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        /**
         * 获取实际宽度
         * spec : 左右边距 margin
         * padding : 左右边距 padding
         */
        int width = ViewGroup.getChildMeasureSpec(0,0,params.width);
        /**
         * 获取实际高度
         */
        int height;
        int tempHeight = params.height;
        if (tempHeight > 0){
            //填充布局
            height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
        }else{
            //不填充
            height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        view.measure(width, height);
    }

    /**
     * 设置顶部布局的上边距，以控制顶部布局的显示与隐藏
     * @param topPadding
     */
    private void setPadding(int topPadding){
        header.setPadding(header.getPaddingLeft(), topPadding,
                header.getPaddingRight(), header.getPaddingBottom());
        header.invalidate();
    }

    /**
     * 记录滚动状态
     * @param view
     * @param scrollState
     */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        this.scrollState = scrollState;
    }

    /**
     * 根据firstVisibleItem判断是否滚动到ListView最顶端
     * @param view
     * @param firstVisibleItem
     * @param visibleItemCount
     * @param totalItemCount
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        bHeader = (firstVisibleItem == 0);
    }

    /**
     * 触摸ListView的事件
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        /**
         * 只在顶端时处理
         */
        if (!bHeader){
            super.onTouchEvent(ev);
        }
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                /**
                 * 记录按下的位置
                 */
                startY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                /**
                 * 计算移动的距离
                 */
                float dist = ev.getY()-startY;
                /**
                 * 根据移动距离切换状态
                 */
                switch (state){
                    case NONE:
                        /**
                         * 当移动距离大于0时，切换到下拉刷新状态
                         */
                        if (dist > 0){
                            state = PULL;
                            refreshView();
                        }
                        break;
                    case PULL:
                        /**
                         * 当移动距离大于一定高度时，切换为松开刷新状态
                         */
                        if (dist > headerHeight+30 && scrollState == SCROLL_STATE_TOUCH_SCROLL){
                            state = RELEASE;
                            refreshView();
                        }
                        break;
                    case RELEASE:
                        if (dist < headerHeight+30){
                            state = PULL;
                            refreshView();
                        } else if (dist <= 0){
                            state = NONE;
                            refreshView();
                        }
                        break;
                }
                /**
                 * 更新顶部布局的高度
                 */
                setPadding((int)(dist-headerHeight));
                break;
            case MotionEvent.ACTION_UP:
                if (state == RELEASE){
                    state = REFRESHING;
                    refreshView();
                    /**
                     * 调用Activity中的刷新方法
                     */
                    if (iRefreshListener != null) {
                        iRefreshListener.onRefresh();
                    }
                }else if (state == PULL){
                    state = NONE;
                    refreshView();
                }
                break;
        }

        return super.onTouchEvent(ev);
    }

    /**
     * 根据状态刷新界面
     */
    private void refreshView(){

        /**
         * 箭头旋转的动画
         **/
        RotateAnimation animation = new RotateAnimation( //箭头朝上
                0,//起始角度
                180,//结束角度
                RotateAnimation.RELATIVE_TO_SELF,//相对自身旋转
                0.5f,//相对位置
                RotateAnimation.RELATIVE_TO_SELF,
                0.5f
                );
        animation.setDuration(500);//动画的时间
        animation.setFillAfter(true);
        RotateAnimation animation1 = new RotateAnimation( //箭头朝下
                180,//起始角度
                0,//结束角度
                RotateAnimation.RELATIVE_TO_SELF,//相对自身旋转
                0.5f,//相对位置
                RotateAnimation.RELATIVE_TO_SELF,
                0.5f
        );
        animation1.setDuration(500);
        animation1.setFillAfter(true);

        switch (state){
            case NONE:
                setPadding(-headerHeight);
                imageArrow.clearAnimation();
                break;
            case PULL:
                imageArrow.setVisibility(View.VISIBLE);
                imageArrow.clearAnimation();
                imageArrow.setAnimation(animation1);
                progressBar.setVisibility(View.GONE);
                refreshTxt.setText("下拉可以刷新");
                break;
            case RELEASE:
                imageArrow.setVisibility(View.VISIBLE);
                imageArrow.clearAnimation();
                imageArrow.setAnimation(animation);
                progressBar.setVisibility(View.GONE);
                refreshTxt.setText("松开可以刷新");
                break;
            case REFRESHING:
                setPadding(0);
                imageArrow.setVisibility(View.GONE);
                imageArrow.clearAnimation();
                progressBar.setVisibility(View.VISIBLE);
                refreshTxt.setText("正在刷新");
                break;
        }
    }

    /**
     * 刷新数据完成的操作
     */
    public void refreshCompleted(){
        //重新获取布局所占的高度
        headerHeight = header.getMeasuredHeight();
        Log.i("tag", headerHeight+"");

        state = NONE;
        refreshView();
        /**
         * 获取系统时间，记录上次刷新时间
         */
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        timeTxt.setText("上次刷新时间："+format.format(date));
    }
}
